/*
 * @Author: wangshuixin 2412658453@qq.com
 * @Date: 2024-09-04 12:34:59
 * @LastEditors: wangshuixin 2412658453@qq.com
 * @LastEditTime: 2024-10-16 12:52:57
 * @FilePath: \web-components-box\components\equation\compose.ts
 * @Description: 生成方程式
 */

import { Message } from "@arco-design/web-vue"
import { type ExpressionTerm, type VariableTermElement } from '~/types/equation'
import { invertFractionTopAndBottom } from '~/utils/number'

// 生成一元一次方程 ax + b = 0
export function createEquationVal_1_power_1(variable: string = 'x', a: string|number = 0, b: string|number = 1) {
  // 
  console.log(convertInverseMatrix());
  
  if (a !== 0) {
    return `${a !== 1 ? a : ''}${variable} + ${b} = 0`
  } else {
    Message.error('方程系数为零，已自动赋值')
    return {
      expression: `${variable} + ${b} = 0`
    }
  }
}

/**
 * @function 简单版方程式
 * @tip 例子：2x + 5y - 7 = 0 
*/
export function easyEquation() {

}

/**
 * @function 拆分未知数变量的系数
 * @argument 标准方程 - 默认所有未知变量已合并同类项，则type仅为‘+’、‘-’、undefined
 * @tip 在矩阵中，忽略type的值为undefined的情况
*/
export function termComposeConstant(term: ExpressionTerm) {
  const constant = {
    ...term, // 只要系数，则注释本行
    constant: term?.constant,
    type: term.type
  } as ExpressionTerm
  return constant
}

/**
 * @function 获取系数矩阵的行向量
 * @tip 例子：2x + 5y - 7 = 0 => [2, 5]
*/
export function constant2RatioMatrixRowVector(allTerms: ExpressionTerm[]) {
  const rowVector = allTerms.map((i: ExpressionTerm) => {
    if (i.variable && i.variable.length) {
      return {
        ...termComposeConstant(i)
      }
    } else {
      return undefined
    }
  }).filter(result => result !== undefined)
  
  return rowVector
}

/**
 * @function 获取增广矩阵的行向量（包含常量系数）
 * @tip 例子：2x + 5y - 7 = 0 =>  [2, 5 , 7]
*/
export function constant2AugmentedMatrixRowVector(allTerms: ExpressionTerm[]) {
  const rowVector = allTerms.map((i: ExpressionTerm) => {
    return {
      ...termComposeConstant(i),
      type: i.variable && i.variable.length ? termComposeConstant(i).type : (termComposeConstant(i).type === '1' ? '2' : '1') // 如果不存在变量，说明为常量，在增广矩阵中需要进行“变号”
    }
  })
  
  return rowVector
}

/**
 * @function 获取系数矩阵
 * @tip 例子：2x + 5y - 7 = 0 && 3x + 7y - 3 = 0 => [[2, 5 , 7], [3, 7, 3]]
*/
export function getRatioMatrixArray(equations: Array<ExpressionTerm[]>) {
  const matrixArray = equations.map((i: ExpressionTerm[]) => {
    return constant2RatioMatrixRowVector(i)
  })
  return matrixArray
}

/**
 * @function 获取增广矩阵
 * @tip 例子：2x + 5y - 7 = 0 && 3x + 7y - 3 = 0 => [[2, 5 , 7], [3, 7, 3]]
*/
export function getAugmentedMatrixArray(equations: Array<ExpressionTerm[]>) {
  const matrixArray = equations.map((i: ExpressionTerm[]) => {
    return constant2AugmentedMatrixRowVector(i)
  })
  return matrixArray
}

/**
 * @function 执行矩阵的初等行变换 - 消除头部系数
 * @tip 将作为“减数”的行向量的第一个元素的系数变为1，消灭它
*/
export function executeMatrixPrimaryRowOperation_Ratio(matrixArray: Array<ExpressionTerm[]>, index: number = 0) { 
  const newMatrixArray = matrixArray
  // 整理第index个行向量的首元素为1
  const rowVector = newMatrixArray[index]
  const factor = invertFractionTopAndBottom(rowVector[index]?.constant![0].number!) // [0].number 这个地方需要进一步扩展
  // 将行向量的每个元素，均同首元素乘以factor系数
  rowVector.forEach((term: ExpressionTerm) => {
    // 可能为undefined，且可以更复杂，需修改
    term.constant![0].number = calculateFactor_multiply(term?.constant![0].number!, factor) // [0].number 这个地方需要进一步扩展
  })
  return newMatrixArray
}

/**
 * @function 执行矩阵的初等行变换 - 消元
 * @tip 将“被减数”的行向量的变量数量进行消减
*/
export function executeMatrixPrimaryRowOperation_Remove(matrixArray: Array<ExpressionTerm[]>, index: number = 0) {
  // 消除头部系数
  const newMatrixArray = executeMatrixPrimaryRowOperation_Ratio(matrixArray, index)
  newMatrixArray.forEach((rowVector: ExpressionTerm[], xIndex: number) => {
    if (xIndex > index) {
      // 被减数第一个元素
      const factor = rowVector[index]?.constant![0].number! // [0].number 这个地方需要进一步扩展
      rowVector.forEach((term: ExpressionTerm, yIndex) => {
        // “减数”行向量的元素
        const subtrahendElement = newMatrixArray[index][yIndex]?.constant![0].number! // [0].number 这个地方需要进一步扩展
        term.constant![0].number = calculateFactor_subtraction(term?.constant![0].number!, calculateFactor_multiply(subtrahendElement, factor)) // [0].number 这个地方需要进一步扩展
      })
    }
  })
  return newMatrixArray
}

/**
 * @function 获取上三角矩阵
 * @tip 利用初等行变换，得到上三角矩阵
*/
export function getUpperTriangleMatrixArray(matrixArray: Array<ExpressionTerm[]>, xCount: number) {
  let newMatrixArray = JSON.parse(JSON.stringify(matrixArray))
  newMatrixArray.map((rowVector: ExpressionTerm[], index: number) => {
    if (index < rowVector.length) {
      executeMatrixPrimaryRowOperation_Remove(newMatrixArray, index)
    }
  })
  return newMatrixArray
}

/**
 * @function 计算矩阵的秩
 * @tip 矩阵的秩，记作：r(A)
*/
export function calculateRankOfMatrixArray(matrixArray: Array<ExpressionTerm[]>, xCount: number) {
  // 默认值：满秩，判断行向量的元素是否都为0，为零向量，则r(A) = r(A) - 1
  let rank = matrixArray.length
  const newMatrixArray = getUpperTriangleMatrixArray(matrixArray, xCount)
  newMatrixArray.map((rowVector: ExpressionTerm[], xIndex: number) => {
    // 假设存在零向量
    let existZeroVector = true
    rowVector.map((term: ExpressionTerm) => {
      if (term.constant![0].number !== '0') {
        existZeroVector = false
      }
    })
    if (existZeroVector) {
      rank--
    }
  })
  return rank
}

/**
 * @function 高斯消元法 - 判断方程组是否有解
 * @param matrixArray 方程组表达式
 * @param xCount 未知数个数
 * @tip 高斯消元法：通过“系数矩阵的秩”和“增广矩阵的秩”来判断方程组是否有解
*/
export function gaussEliminationMethod2SolveEquations(matrixArray: Array<ExpressionTerm[]>, xCount: number) {
  // 系数矩阵
  const ratioMatrixArray = getRatioMatrixArray(matrixArray)
  const upperRatio = getUpperTriangleMatrixArray(ratioMatrixArray, xCount)
  // 计算系数矩阵的秩
  const ratioRank = calculateRankOfMatrixArray(upperRatio, xCount)
  // 增广矩阵
  const augmentedMatrixArray = getAugmentedMatrixArray(matrixArray)
  const upperAugmented = getUpperTriangleMatrixArray(augmentedMatrixArray, xCount)
  // 计算增广矩阵的秩
  const augmentedRank = calculateRankOfMatrixArray(upperAugmented, xCount)
  // 系数矩阵的秩 不可能大于 增广矩阵的秩
  if (ratioRank < augmentedRank) {
    return {
      msg: "方程组无解",
      type: 0,
      data: undefined
    }
  } else if (ratioRank === augmentedRank && ratioRank === xCount) {
    return {
      msg: "方程组有唯一解",
      type: 1,
      data: gaussEliminationMethod2BackSubstitution(upperAugmented, xCount)
    }
  } else if (ratioRank === augmentedRank && ratioRank < xCount) {
    return {
      msg: "方程组有无穷多解",
      type: -1,
      data: []
    }
  }
}

/**
 * @function 高斯消元法求解 - 回代
 * @param matrixArray 上三角增广矩阵表达式
 * @param xCount 未知数个数 = 行向量元素数 - 1
 * @attention 非齐次线性方程组求解
 * @tip 高斯消元法：通过“系数矩阵的秩”和“增广矩阵的秩”来判断方程组是否有解
*/
export function gaussEliminationMethod2BackSubstitution(matrixArray: Array<ExpressionTerm[]>, xCount: number) {
  // 为了使matrixArray数据不被污染
  const newMatrixArray = JSON.parse(JSON.stringify(matrixArray))
  // 变量的值，从后往前放置未知数的解
  let xValueArr = []
  // 按坐标，从大到小遍历行向量的元素
  for (let rowIndex = xCount - 1; rowIndex > -1; rowIndex--) {
    const rowVector = newMatrixArray[rowIndex];
    // 常数项
    const constantTerm = rowVector[xCount]
    const constantRatio = constantTerm?.constant[0].number
    xValueArr.push(constantRatio)
    // 根据传入的变量，从后往前获取变量的解
    let xValue: any = xValueArr[xCount - 1 - rowIndex]
    for (let colIndex = xCount - 1; colIndex > rowIndex; colIndex--) {
      const colTerm = rowVector[colIndex] 
      // 项的系数
      const termRatio = colTerm?.constant[0].number
      xValue = calculateFactor_subtraction(xValue, calculateFactor_multiply(termRatio, xValueArr[xCount - 1 - colIndex]))
    }
    xValueArr[xCount - 1 - rowIndex] = xValue
  }
  return xValueArr
}